package com.spsa.vista.controladores;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;

import com.spsa.excepciones.EstadoIlegalExcepcion;
import com.spsa.excepciones.ServicioException;
import com.spsa.excepciones.SistemaException;
import com.spsa.negocio.servicios.ServicioEstadosTiendas;
import com.spsa.negocio.servicios.ServicioGeneracionReportes;
import com.spsa.negocio.utilidades.SingletonDatos;
import com.spsa.persistencia.entidades.EstadoInterfaz;
import com.spsa.persistencia.entidades.Interfaz;
import com.spsa.persistencia.entidades.Reporte;
import com.spsa.persistencia.entidades.Tienda;
import com.spsa.vista.utilidades.MensajesJSF;

@ManagedBean(name = "estadoTiendas")
@ViewScoped
public class ControladorEstadoTiendas implements Serializable {
	
	static final Logger logger = LogManager.getLogger(ControladorEstadoTiendas.class.getName());
	
	@EJB
	private SingletonDatos singletonDatos;
	@EJB
	private ServicioEstadosTiendas servicioEstadoTiendas;
	@EJB
	private ServicioGeneracionReportes servicioReportes;
	private int numTablas = 4;
	private int numFilas = 30;
	private int numeroTiendasRojo = 0;
	private int numeroTiendasVerde;
	private int numeroTiendasBlanco;
	private StreamedContent archivoReporte;
	private List<Interfaz> interfaces;
	private Interfaz interfaz;
	private List<EstadoInterfaz> estados;
	private List<List<EstadoInterfaz>> estadosPorTablas;
	private int numeroTiendasAzul;

	@PostConstruct
	public void inicializar() {
		interfaces = singletonDatos.getInterfaces();
		interfaz = interfaces.get(0);
		cargarEstadosTiendas();
	}

	public void generarReporte() {
		try {
			Reporte reporte = servicioReportes.crearReporte(estados, interfaz);
			InputStream stream = new FileInputStream(reporte.getRutaReporte());
			archivoReporte = new DefaultStreamedContent(stream, "txt", "ReporteTiendasEnRojo.txt");
			MensajesJSF.mostrarMensaje("Reporte", "Reporte generado");
		} catch (ServicioException e) {
			MensajesJSF.mostrarError("Error al generar el reporte", e.getMessage());
		} catch (FileNotFoundException e) {
			MensajesJSF.mostrarError("Error al descargar el reporte", "No se encontro el archivo del reporte");
		}
	}

	public StreamedContent getArchivoReporte() {
		generarReporte();
		return archivoReporte;
	}

	public void mostrarEstadoInterfaz(SelectEvent event) {
		cargarEstadosTiendas();
	}

	private void cargarEstadosTiendas() {
		try {
			estados = servicioEstadoTiendas.listarPorInterfaz(interfaz);
			distribuirEstadosTiendasEnLasTablas();
			contarTiendasRojoVerde();
		} 
		catch(ServicioException e) {
			MensajesJSF.mostrarError("Mostrar estado de tiendas", e.getMessage());
		}
	}

	private void distribuirEstadosTiendasEnLasTablas() {
		estadosPorTablas = new ArrayList<List<EstadoInterfaz>>();

		int numEstados = estados.size();
		int limiteInf = 0, limiteSup;
		
		for(int i = 0; i < numTablas; i ++) {
			List<EstadoInterfaz> estadoTabla = new ArrayList<EstadoInterfaz>();
			
			limiteInf = i * numFilas;
			limiteSup = Math.min(estados.size(), (i+1)*numFilas);
			
			if(limiteSup > numEstados || limiteInf > limiteSup) {
				estadosPorTablas.add(estadoTabla);
				continue;
			}
			
			estadoTabla = estados.subList(limiteInf, limiteSup);
			estadosPorTablas.add(estadoTabla);
		}
	}

	private void contarTiendasRojoVerde() {
		numeroTiendasRojo = servicioEstadoTiendas.obtenerCantidadTiendasRojo(estados);
		numeroTiendasVerde = servicioEstadoTiendas.obtenerCantidadTiendasVerde(estados);
		numeroTiendasBlanco = servicioEstadoTiendas.obtenerCantidadTiendasBlanco(estados);
		numeroTiendasAzul = estados.size() - numeroTiendasRojo - numeroTiendasVerde - numeroTiendasBlanco;
	}

	public List<Interfaz> filtrarInterfaz(String prefijo) {
		prefijo = prefijo.trim().toLowerCase();

		List<Interfaz> interfacesFiltradas = new ArrayList<Interfaz>();

		for (Interfaz interfaz : interfaces) {
			if (interfaz.getDescripcion().toLowerCase().startsWith(prefijo))
				interfacesFiltradas.add(interfaz);
		}

		return interfacesFiltradas;
	}

	public void actualizar() {
		cargarEstadosTiendas();
	}

	public Tienda getTienda(String codigoTienda) { 
		try {
			return singletonDatos.buscarTienda(codigoTienda);
		}
		catch(EstadoIlegalExcepcion e) {
			MensajesJSF.mostrarError("Cargar Estado de las Tiendas", "No se pudo recuperar los datos de la Tienda con codigo: " + codigoTienda);
			throw new SistemaException("No se pudo recuperar los datos de la Tienda con codigo: " + codigoTienda);
		}
		
	}
	
	public List<Interfaz> getInterfaces() {
		return interfaces;
	}

	public void setInterfaces(List<Interfaz> interfaces) {
		this.interfaces = interfaces;
	}

	public Interfaz getInterfaz() {
		return interfaz;
	}

	public void setInterfaz(Interfaz interfaz) {
		for(int i = 0; i < interfaces.size(); i ++) {
			if(interfaces.get(i).getDescripcion().equals(interfaz.getDescripcion())) {
				this.interfaz = interfaces.get(i);
				return;
			}
		}
	}

	public int getNumeroTiendasRojo() {
		return numeroTiendasRojo;
	}

	public void setNumeroTiendasRojo(int numeroTiendasRojo) {
		this.numeroTiendasRojo = numeroTiendasRojo;
	}

	public void setArchivoReporte(StreamedContent archivoReporte) {
		this.archivoReporte = archivoReporte;
	}

	public int getNumeroTiendasVerde() {
		return numeroTiendasVerde;
	}

	public void setNumeroTiendasVerde(int numeroTiendasVerde) {
		this.numeroTiendasVerde = numeroTiendasVerde;
	}

	public int getNumFilas() {
		return numFilas;
	}

	public void setNumFilas(int numFilas) {
		this.numFilas = numFilas;
	}

	public List<List<EstadoInterfaz>> getEstadosPorTablas() {
		return estadosPorTablas;
	}

	public void setEstadosPorTablas(List<List<EstadoInterfaz>> estadosPorTablas) {
		this.estadosPorTablas = estadosPorTablas;
	}

	public int getNumTablas() {
		return numTablas;
	}

	public void setNumTablas(int numTablas) {
		this.numTablas = numTablas;
	}

	public int getNumeroTiendasBlanco() {
		return numeroTiendasBlanco;
	}

	public void setNumeroTiendasBlanco(int numeroTiendasBlanco) {
		this.numeroTiendasBlanco = numeroTiendasBlanco;
	}

	public int getNumeroTiendasAzul() {
		return numeroTiendasAzul;
	}

	public void setNumeroTiendasAzul(int numeroTiendasAzul) {
		this.numeroTiendasAzul = numeroTiendasAzul;
	}
}
